package cn.itcast.demo.lock;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;

import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author 虎哥
 */
public class SimpleRedisLock implements RedisLock {

    private final StringRedisTemplate redisTemplate;
    private final String key;
    private final String THREAD_PREFIX;

    public SimpleRedisLock(StringRedisTemplate redisTemplate, String key) {
        this.redisTemplate = redisTemplate;
        this.key = key;
        this.THREAD_PREFIX = UUID.randomUUID().toString() + "_";
    }

    @Override
    public boolean tryLock(long releaseTime) {
        // 生成线程标示
        String value =THREAD_PREFIX +  Thread.currentThread().getId();
        // 执行 set key value nx ex time
        Boolean boo = false;
        while (!boo) {
            boo = redisTemplate.opsForValue().setIfAbsent(key, value, releaseTime, TimeUnit.SECONDS);
        }
        // 返回结果
        return boo;
    }

    @Override
    public void unLock() {
        // 生成线程标示
        String value =THREAD_PREFIX +  Thread.currentThread().getId();
        // 获取脚本
        RedisScript<Object> script = RedisScript.of("if (ARGV[1] == redis.call('get', KEYS[1])) then\n" +
                "    redis.call('del', KEYS[1])\n" +
                "end");
        // 执行脚本
        redisTemplate.execute(script, Collections.singletonList(key), value);
    }
}
